package scaladuct.memento

import scaladuct._
import l10n._
import LookupFunctions._
import java.lang.String

/**
 * <p>
 * Created by IntelliJ IDEA.
 * User: zslajchrt
 * Date: Aug 17, 2010
 * Time: 8:47:37 PM
 */

trait MementoRecordingGateway[X] extends GatewayWithHints[X]
with MementoGatewayBase {

  case object SaveMementoMenu extends CompactProperty {
    def createPage() = PhaseMethodInterceptor[Any](classOf[SaveMementoStarter], (summary: StoredMementoConfig) => {
      summary.parameterProperties = parameterProperties.filter(_._2.record)
      saveMemento(summary)
    }).page
  }

  case class ParameterPropertyMenu(record: Boolean, selectedPropertyKey: SelectedParameterKey,
                                   cookieProperty: PropertyValue[AnyRef])
    extends MutablePropertyValue[Boolean](
      "ParameterPropertyMenu", record, classOf[Boolean])

  private[this] val config = new MementoRecorderConfig
  private[this] var recordedCookies = Map.empty[String, AnyRef]

  private[this] var parameterProperties = Map.empty[SelectedParameterKey, ParameterProperty]

  protected def saveMemento(storedMementoConfig: StoredMementoConfig)

  def isMementoParameter(propertyName: String): Boolean = {
    //parameterProperties.contains(Memento.absolutePropertyId(getCurrentPage.id, propertyName))
    parameterProperties.contains(SelectedParameterKey(getCurrentPage.id, propertyName))
  }

  private def getCookieProperty(propName: String): PropertyValue[AnyRef] = {
    val cookieBean = CookieBeanFactory(getCookie)
    cookieBean.property(propName) match {
      case None => error("Expected property " + propName + " in cookie " + getCookie)
      case Some(prop) => prop
    }
  }

  override def hints(subject: String): List[Property[Any]] = if (subject == null)
    if (config.record) {
      SaveMementoMenu :: super.hints(subject)
    } else super.hints(subject)
  else {
    //val parameterId: String = Memento.absolutePropertyId(getCurrentPage.id, subject)
    val parameterKey = SelectedParameterKey(getCurrentPage.id, subject)
    new ParameterPropertyMenu(parameterProperties.get(parameterKey) match {
      case None => false
      case Some(parameterProperty) => parameterProperty.record
    }, parameterKey, getCookieProperty(subject)) :: super.hints(subject)
  }

  override def hintPage(hint: Property[Any]): ConfigPage[Any] = {
    hint match {
    //      case MementoRecorderConfigMenu => {
    //        MementoRecorderConfigMenu.createPage
    //      }
      case SaveMementoMenu => {
        SaveMementoMenu.createPage
      }
      case recordMenuItem: ParameterPropertyMenu => {
        if (recordMenuItem.value)
          parameterProperties +=
            (recordMenuItem.selectedPropertyKey -> new ParameterProperty(getCurrentPage.id,
              recordMenuItem.cookieProperty,
              recordMenuItem.value))
        else
          parameterProperties -= recordMenuItem.selectedPropertyKey
        null
      }
      case _ => super.hintPage(hint)
    }
  }

  private def recordCookie(id: String, cookie: AnyRef) {
    recordedCookies += (id -> cookie)
  }

  override def unconsume() = {
    super.unconsume
    recordedCookies.filter((pair: (String, AnyRef)) => {
      val (pageId, _) = pair
      pageId == id
    })
  }
}

@serializable
@SerialVersionUID(1L)
class MementoRecorderConfig {
  var record: Boolean = true
  var p1: String = "aaa"
  var p2: Int = 12
  var p3: String = "xyz"
  var p4: Boolean = false
}

@serializable
@SerialVersionUID(1L)
class StoredMementoConfig {
  var name: String = null
  var parameterProperties = Map.empty[SelectedParameterKey, ParameterProperty]
}

@SerialVersionUID(1L)
class SaveMementoStarter(saver: (StoredMementoConfig) => Unit) extends Starter[Null] {

  def newInstance(): Null = phase1(null)

  def phase1(@Name("name") name: String): Null = {
    val storeConfig = new StoredMementoConfig
    storeConfig.name = name
    saver(storeConfig)
    null
  }

  def destroy(instance: Null) = null

}

@serializable
@SerialVersionUID(1L)
case class SelectedParameterKey(pageId: String, propertyName: String)

//@deprecated
//@SerialVersionUID(1L)
//class MementoSummaryStarter[X](summary: StoredMementoConfig,
//                               storage: MementoStorage,
//                               recordedCookies: Map[String, AnyRef],
//                               parameterProperties: Map[String, ParameterProperty],
//                               wrappedStarter: Starter[X]) extends Starter[X] {
//  def destroy(instance: X) = wrappedStarter.destroy(instance)
//
//  def newInstance(): X = phase1(summary)
//
//  def phase1(summary: StoredMementoConfig): X = {
//    val memento = new Memento(summary.name, recordedCookies, parameterProperties)
//    storage.storeMemento(memento)
//    wrappedStarter.newInstance
//  }
//}

//class RecordPropertyConfig {
//  var recordProperty: Boolean = false
//}
//
//class RecordPropertyMenuStarter extends Starter[Null] {
//  def newInstance() = phase1(false)
//
//  def phase1(recordProperty: Boolean): Null = null
//
//  def destroy(instance: Null) = null
//}
